home *** CD-ROM | disk | FTP | other *** search
/ JCSM Shareware Collection 1993 November / JCSM Shareware Collection - 1993-11.iso / cl720 / tsrtoo15.lzh / TSR.C < prev    next >
C/C++ Source or Header  |  1993-09-04  |  51KB  |  1,975 lines

  1. /*
  2.     tsr.C
  3.  
  4.     Version 1.5
  5.  
  6.     Generate TSR .ASM file or view resident TSRs.
  7.  
  8.     Command-line format:
  9.  
  10.     tsr options tsrspec
  11.  
  12.     options = map | [hotkey] [include] [setup_cleanup] [stack] [xparse]
  13.  
  14.     map = ("/"|"-") "m"
  15.     hotkey = ("/"|"-") "h" x
  16.     include = ("/"|"-") "i"
  17.     setup_cleanup = ("/"|"-") "sc"
  18.     stack = ("/"|"-") "s" y
  19.     xparse = ("/"|"-") "x"
  20.  
  21.     x is either "A"-"Z" or "0"-"9" (default is T)
  22.     y is a byte value from 256 to 8192 (default is 256)
  23.     tsrspec defines the .TSR file to be TSRed
  24.  
  25.     Copyright (C) 1993, Geoff Friesen B.Sc.
  26.     All rights reserved.
  27.  
  28.     Developed with: Borland C++ 3.1
  29. */
  30.  
  31. #if !defined(__LARGE__)
  32. #error Large Memory Model Expected
  33. #endif
  34.  
  35. #include <ctype.H>
  36. #include <dir.H>
  37. #include <dos.H>
  38. #include <process.H>
  39. #include <stdio.H>
  40. #include <stdlib.H>
  41. #include <string.H>
  42.  
  43. #define    OK    0
  44. #define    ERROR    !OK
  45.  
  46. #define    IGNORE    1
  47.  
  48. #define    FREEMCB    0
  49. #define    BLOCMCB    'M'
  50. #define    LASTMCB    'Z'
  51.  
  52. #define    KEYOFS    0x103
  53. #define    SIGOFS    0x10d
  54.  
  55. /* --------------------------------------------------------------------- */
  56.  
  57. char *listing1 =
  58.  
  59. "\n\n"
  60. "_TEXT\t\tSEGMENT\tBYTE PUBLIC 'CODE'\n"
  61. "\t\tASSUME\tcs:_TEXT, ds:NOTHING, es:NOTHING, ss:NOTHING\n"
  62. "\t\tORG\t100h\n"
  63. "\n"
  64. "CR\t\tEQU\t13\n"
  65. "LF\t\tEQU\t10\n"
  66. "TAB\t\tEQU\t9\n"
  67. "\n"
  68. "INACTIVE\tEQU\t0\t\t; TSR not active.\n"
  69. "TRIGGERED\tEQU\t1\t\t; TSR triggered.\n"
  70. "ACTIVE\t\tEQU\t2\t\t; TSR active.\n"
  71. "\n"
  72. "tsr:\n"
  73. "\t\tjmp\tNEAR PTR install\n"
  74. "\n"
  75. "; ----------------------- ;\n"
  76. "; Personal Identification ;\n"
  77. "; ----------------------- ;\n"
  78. "\n"
  79. "key\t\tDB\t'";
  80.  
  81. /* --------------------------------------------------------------------- */
  82.  
  83. char *listing2 =
  84.  
  85. "'\t\t; Hotkey character.\n"
  86. "scancode\tDB\t";
  87.  
  88. /* --------------------------------------------------------------------- */
  89.  
  90. char *listing3 =
  91.  
  92. "\t\t; Activation scancode.\n"
  93. "\t\tDB\t0\n"
  94. "\t\tDB\t2\t\t; Version number.\n"
  95. "\t\tDW\t_main\t\t; Application start address.\n"
  96. "\t\tDW\tinstallsec\t; Application end address+1.\n"
  97. "\t\tDW\t0\t\t; Reserved.\n"
  98. "signature\tDB\t";
  99.  
  100. /* --------------------------------------------------------------------- */
  101.  
  102. char *listing4 =
  103.  
  104. "\t; Our signature in memory.\n"
  105. "SIGLENGTH\tEQU\t$-signature\t; Length of this signature.\n"
  106. "\t\tDB\t0\n"
  107. "\n"
  108. "; --------------------- ;\n"
  109. "; Resident Data Section ;\n"
  110. "; --------------------- ;\n"
  111. "\n"
  112. "beepf\t\tDB\t0\t\t; Beep when TSR triggered flag.\n"
  113. "critdisk\tDB\t0\t\t; Critical disk flag.\n"
  114. "criterr\t\tDD\t?\t\t; Address of critical error flag.\n"
  115. "critsec\t\tDD\t?\t\t; Address of critical section flag.\n"
  116. "dta\t\tDD\t?\t\t; Saved DTA address.\n"
  117. "errax\t\tDW\t?\t\t; Saved extended error info.\n"
  118. "errbx\t\tDW\t?\n"
  119. "errcx\t\tDW\t?\n"
  120. "oldint8h\tDD\t?\t\t; Old interrupt 8h vector.\n"
  121. "oldint8h_\tDD\t?\n"
  122. "oldint9h\tDD\t?\t\t; Old interrupt 9h vector.\n"
  123. "oldint9h_\tDD\t?\n"
  124. "oldint13h\tDD\t?\t\t; Old interrupt 13h vector.\n"
  125. "oldint16h\tDD\t?\t\t; Old interrupt 16h vector.\n"
  126. "oldint16h_\tDD\t?\n"
  127. "oldint1bh\tDD\t?\t\t; Old interrupt 1bh vector.\n"
  128. "oldint1ch\tDD\t?\t\t; Old interrupt 1ch vector.\n"
  129. "oldint1ch_\tDD\t?\n"
  130. "oldint23h\tDD\t?\t\t; Old interrupt 23h vector.\n"
  131. "oldint24h\tDD\t?\t\t; Old interrupt 24h vector.\n"
  132. "oldint28h\tDD\t?\t\t; Old interrupt 28h vector.\n"
  133. "oldint2fh\tDD\t?\t\t; Old interrupt 2fh vector.\n"
  134. "port61h\t\tDB\t?\t\t; Current value in port 61h.\n"
  135. "psp_\t\tDW\t?\t\t; Saved PSP.\n"
  136. "savesp\t\tDW\t?\t\t; Saved stack pointer.\n"
  137. "savess\t\tDW\t?\t\t; Saved stack segment.\n"
  138. "tsr_state\tDB\tINACTIVE\t; TSR state.\n"
  139. "XMS_driver\tDD\t0\t\t; Address of XMS driver.\n"
  140. "XMS_inuse\tDB\t0\t\t; XMS inuse flag.\n"
  141. "\n"
  142. "; --------------------- ;\n"
  143. "; Resident Code Section ;\n"
  144. "; --------------------- ;\n"
  145. "\n"
  146. "; ----------------------- ;\n"
  147. "; New interrupt 8h vector ;\n"
  148. "; ----------------------- ;\n"
  149. "\n"
  150. "newint8h\tPROC\tFAR\n"
  151. "\t\tpushf\n"
  152. "\t\tcall\tDWORD PTR oldint8h\n"
  153. "\n"
  154. "\t\tcmp\tBYTE PTR tsr_state, TRIGGERED\n"
  155. "\t\tjnz\tnewint8h1\n"
  156. "\n"
  157. "\t\tpush\tax\n"
  158. "\t\tpush\tbx\n"
  159. "\t\tpush\tes\n"
  160. "\n"
  161. "\t\tles\tbx, DWORD PTR criterr\n"
  162. "\t\tmov\tal, es:[bx]\n"
  163. "\n"
  164. "\t\tcmp\tal, 0\n"
  165. "\n"
  166. "\t\tpop\tes\n"
  167. "\t\tpop\tbx\n"
  168. "\t\tpop\tax\n"
  169. "\n"
  170. "\t\tjnz\tnewint8h1\n"
  171. "\n"
  172. "\t\tpush\tax\n"
  173. "\t\tpush\tbx\n"
  174. "\t\tpush\tes\n"
  175. "\n"
  176. "\t\tles\tbx, DWORD PTR critsec\n"
  177. "\t\tmov\tal, es:[bx]\n"
  178. "\n"
  179. "\t\tcmp\tal, 0\n"
  180. "\n"
  181. "\t\tpop\tes\n"
  182. "\t\tpop\tbx\n"
  183. "\t\tpop\tax\n"
  184. "\n"
  185. "\t\tjnz\tnewint8h1\n"
  186. "\n"
  187. "\t\tcmp\tBYTE PTR critdisk, 0\n"
  188. "\t\tjnz\tnewint8h1\n"
  189. "\n"
  190. "\t\tcmp\tBYTE PTR XMS_inuse, 0\n"
  191. "\t\tjnz\tnewint8h1\n"
  192. "\n"
  193. "\t\tmov\tBYTE PTR tsr_state, ACTIVE\n"
  194. "\n"
  195. "\t\tcall\tlaunch\n"
  196. "\n"
  197. "\t\tmov\tBYTE PTR tsr_state, INACTIVE\n"
  198. "newint8h1:\n"
  199. "\t\tiret\n"
  200. "newint8h\tENDP\n"
  201. "\n"
  202. "; ----------------------- ;\n"
  203. "; New interrupt 9h vector ;\n"
  204. "; ----------------------- ;\n"
  205. "\n"
  206. "newint9h\tPROC\tFAR\n"
  207. "\t\tpush\tax\n"
  208. "\n"
  209. "\t\tin\tal, 60h\t\t; Examine scan code.\n"
  210. "\n"
  211. "\t\tcmp\tal, scancode\t; Does it match our scan code?\n"
  212. "\t\tjz\tnewint9h2\t; Yes, branch.\n"
  213. "newint9h1:\n"
  214. "\t\tpop\tax\t\t; Exit to original handler.\n"
  215. "\t\tjmp\tDWORD PTR oldint9h\n"
  216. "newint9h2:\n"
  217. "\t\tpush\tes\t\t; Check for simultaneous ALT press.\n"
  218. "\t\tmov\tax, 0\n"
  219. "\t\tmov\tes, ax\n"
  220. "\n"
  221. "\t\tmov\tal, es:[417h]\t; Get shift status byte.\n"
  222. "\t\tand\tal, 15\t\t; Remove toggle data.\n"
  223. "\t\tcmp\tal, 8\t\t; ALT (alone) pressed?\n"
  224. "\n"
  225. "\t\tpop\tes\n"
  226. "\t\tjnz\tnewint9h1\t; No, branch.\n"
  227. "\n"
  228. "\t\tin\tal, 61h\t\t; Acknowledge scan code.\n"
  229. "\t\tjmp\t$+2\n"
  230. "\t\tmov\tah, al\n"
  231. "\t\tor\tal, 10000000b\n"
  232. "\t\tout\t61h, al\n"
  233. "\t\tjmp\t$+2\n"
  234. "\t\tmov\tal, ah\n"
  235. "\t\tout\t61h, al\n"
  236. "\t\tjmp\t$+2\n"
  237. "\n"
  238. "\t\tcmp\tBYTE PTR tsr_state, INACTIVE\n"
  239. "\t\tjnz\tnewint9h4\t; Branch if TSR not inactive.\n"
  240. "\n"
  241. "\t\tcmp\tbeepf, 0\t; Can we beep?\n"
  242. "\t\tjz\tnewint9h3\t; No, branch.\n"
  243. "\n"
  244. "\t\tin\tal, 61h\t\t; Save port value.\n"
  245. "\t\tmov\tport61h, al\n"
  246. "\n"
  247. "\t\tand\tal, 0fch\t; Disconnect speaker.\n"
  248. "\t\tout\t61h, al\n"
  249. "\n"
  250. "\t\tsti\n"
  251. "\t\tcall\t_beep\t\t; Generate a beep.\n"
  252. "\t\tcli\n"
  253. "\n"
  254. "\t\tmov\tal, port61h\t; Restore port value.\n"
  255. "\t\tout\t61h, al\n"
  256. "newint9h3:\n"
  257. "\t\tmov\tBYTE PTR tsr_state, TRIGGERED\n"
  258. "newint9h4:\n"
  259. "\t\tmov\tal, 20h\t\t; Reset 8259 PIC.\n"
  260. "\t\tout\t20h, al\n"
  261. "\n"
  262. "\t\tpop\tax\n"
  263. "\n"
  264. "\t\tiret\n"
  265. "newint9h\tENDP\n"
  266. "\n"
  267. "; ------------------------ ;\n"
  268. "; New interrupt 13h vector ;\n"
  269. "; ------------------------ ;\n"
  270. "\n"
  271. "newint13h\tPROC\tFAR\n"
  272. "\t\tmov\tBYTE PTR critdisk, 1\n"
  273. "\n"
  274. "\t\tpushf\n"
  275. "\t\tcall\tDWORD PTR oldint13h\n"
  276. "\n"
  277. "\t\tmov\tBYTE PTR critdisk, 0\n"
  278. "\n"
  279. "\t\tsti\n"
  280. "\n"
  281. "\t\tret\t2\t\t; Return without original flags.\n"
  282. "newint13h\tENDP\n"
  283. "\n"
  284. "; ------------------------ ;\n"
  285. "; New interrupt 1bh vector ;\n"
  286. "; ------------------------ ;\n"
  287. "\n"
  288. "newint1bh\tPROC\tFAR\n"
  289. "\t\tiret\n"
  290. "newint1bh\tENDP\n"
  291. "\n"
  292. "; ------------------------ ;\n"
  293. "; New interrupt 23h vector ;\n"
  294. "; ------------------------ ;\n"
  295. "\n"
  296. "newint23h\tPROC\tFAR\n"
  297. "\t\tiret\n"
  298. "newint23h\tENDP\n"
  299. "\n"
  300. "; ------------------------ ;\n"
  301. "; New interrupt 24h vector ;\n"
  302. "; ------------------------ ;\n"
  303. "\n"
  304. "newint24h\tPROC\tFAR\n"
  305. "\t\tmov\tax, 3\t\t; Fail code.\n"
  306. "\n"
  307. "\t\tiret\n"
  308. "newint24h\tENDP\n"
  309. "\n"
  310. "; ------------------------ ;\n"
  311. "; New interrupt 28h vector ;\n"
  312. "; ------------------------ ;\n"
  313. "\n"
  314. "newint28h\tPROC\tFAR\n"
  315. "\t\tpushf\n"
  316. "\t\tcall\tDWORD PTR oldint28h\n"
  317. "\n"
  318. "\t\tcmp\tBYTE PTR tsr_state, TRIGGERED\n"
  319. "\t\tjnz\tnewint28h1\n"
  320. "\n"
  321. "\t\tpush\tax\n"
  322. "\t\tpush\tbx\n"
  323. "\t\tpush\tes\n"
  324. "\n"
  325. "\t\tles\tbx, DWORD PTR criterr\n"
  326. "\t\tmov\tal, es:[bx]\n"
  327. "\n"
  328. "\t\tcmp\tal, 0\n"
  329. "\n"
  330. "\t\tpop\tes\n"
  331. "\t\tpop\tbx\n"
  332. "\t\tpop\tax\n"
  333. "\n"
  334. "\t\tjnz\tnewint28h1\n"
  335. "\n"
  336. "\t\tpush\tax\n"
  337. "\t\tpush\tbx\n"
  338. "\t\tpush\tes\n"
  339. "\n"
  340. "\t\tles\tbx, DWORD PTR critsec\n"
  341. "\t\tmov\tal, es:[bx]\n"
  342. "\n"
  343. "\t\tcmp\tal, 1\n"
  344. "\n"
  345. "\t\tpop\tes\n"
  346. "\t\tpop\tbx\n"
  347. "\t\tpop\tax\n"
  348. "\n"
  349. "\t\tja\tnewint28h1\n"
  350. "\n"
  351. "\t\tcmp\tBYTE PTR critdisk, 0\n"
  352. "\t\tjnz\tnewint28h1\n"
  353. "\n"
  354. "\t\tcmp\tBYTE PTR XMS_inuse, 0\n"
  355. "\t\tjnz\tnewint28h1\n"
  356. "\n"
  357. "\t\tmov\tBYTE PTR tsr_state, ACTIVE\n"
  358. "\n"
  359. "\t\tcall\tlaunch\n"
  360. "\n"
  361. "\t\tmov\tBYTE PTR tsr_state, INACTIVE\n"
  362. "newint28h1:\n"
  363. "\t\tiret\n"
  364. "newint28h\tENDP\n"
  365. "\n"
  366. "; ------------------------ ;\n"
  367. "; New interrupt 2fh vector ;\n"
  368. "; ------------------------ ;\n"
  369. "\n"
  370. "newint2fh\tPROC\tFAR\n"
  371. "\t\tcmp\tax, 4310h\n"
  372. "\t\tjz\tnewint2fh1\n"
  373. "\n"
  374. "\t\tjmp\tDWORD PTR cs:oldint2fh\n"
  375. "newint2fh1:\n"
  376. "\t\tmov\tbx, OFFSET XMS_rdriver\n"
  377. "\t\tpush\tcs\n"
  378. "\t\tpop\tes\n"
  379. "\n"
  380. "\t\tiret\n"
  381. "newint2fh\tENDP\n"
  382. "\n"
  383. "; ------------------------------ ;\n"
  384. "; Launch: Launch TSR Application ;\n"
  385. "; ------------------------------ ;\n"
  386. "\n"
  387. "\t\tASSUME\tds:_TEXT, es:_TEXT, ss:_TEXT\n"
  388. "\n"
  389. "launch\t\tPROC\tNEAR\n"
  390. "\t\tmov\tcs:savess, ss\t; Switch stacks.\n"
  391. "\t\tmov\tcs:savesp, sp\n"
  392. "\t\tmov\tsp, cs\n"
  393. "\t\tmov\tss, sp\n"
  394. "\t\tlea\tsp, stack_\n"
  395. "\t\tsti\n"
  396. "\n"
  397. "\t\tcld\n"
  398. "\t\tpush\tax\n"
  399. "\t\tpush\tbx\n"
  400. "\t\tpush\tcx\n"
  401. "\t\tpush\tdx\n"
  402. "\t\tpush\tsi\n"
  403. "\t\tpush\tdi\n"
  404. "\t\tpush\tbp\n"
  405. "\t\tpush\tds\n"
  406. "\t\tpush\tes\n"
  407. "\n"
  408. "\t\tpush\tcs\n"
  409. "\t\tpop\tds\n"
  410. "\n"
  411. "\t\tmov\tax, 351bh\n"
  412. "\t\tint\t21h\n"
  413. "\n"
  414. "\t\tmov\tWORD PTR oldint1bh, bx\n"
  415. "\t\tmov\tWORD PTR oldint1bh [2], es\n"
  416. "\n"
  417. "\t\tmov\tax, 3523h\n"
  418. "\t\tint\t21h\n"
  419. "\n"
  420. "\t\tmov\tWORD PTR oldint23h, bx\n"
  421. "\t\tmov\tWORD PTR oldint23h [2], es\n"
  422. "\n"
  423. "\t\tmov\tax, 3524h\n"
  424. "\t\tint\t21h\n"
  425. "\n"
  426. "\t\tmov\tWORD PTR oldint24h, bx\n"
  427. "\t\tmov\tWORD PTR oldint24h [2], es\n"
  428. "\n"
  429. "\t\tlea\tdx, newint1bh\n"
  430. "\t\tmov\tax, 251bh\n"
  431. "\t\tint\t21h\n"
  432. "\n"
  433. "\t\tlea\tdx, newint23h\n"
  434. "\t\tmov\tax, 2523h\n"
  435. "\t\tint\t21h\n"
  436. "\n"
  437. "\t\tlea\tdx, newint24h\n"
  438. "\t\tmov\tax, 2524h\n"
  439. "\t\tint\t21h\n"
  440. "\n"
  441. "\t\tmov\tah, 62h\t\t; Save current PSP.\n"
  442. "\t\tint\t21h\n"
  443. "\n"
  444. "\t\tmov\tpsp_, bx\n"
  445. "\n"
  446. "\t\tmov\tbx, cs\t\t; Set PSP to our own.\n"
  447. "\t\tmov\tah, 50h\n"
  448. "\t\tint\t21h\n"
  449. "\n"
  450. "\t\tmov\tah, 2fh\t\t; Save current DTA.\n"
  451. "\t\tint\t21h\n"
  452. "\n"
  453. "\t\tmov\tWORD PTR dta, bx\n"
  454. "\t\tmov\tWORD PTR dta [2], es\n"
  455. "\n"
  456. "\t\tmov\tdx, 80h\t\t; Set DTA to our own.\n"
  457. "\t\tmov\tah, 1ah\n"
  458. "\t\tint\t21h\n"
  459. "\n"
  460. "\t\tmov\tbx, 0\t\t; Must be zero.\n"
  461. "\t\tmov\tah, 59h\t\t; Save extended error info.\n"
  462. "\t\tint\t21h\n"
  463. "\n"
  464. "\t\tpush\tcs\t\t; DS destroyed by function.\n"
  465. "\t\tpop\tds\n"
  466. "\n"
  467. "\t\tmov\terrax, ax\n"
  468. "\t\tmov\terrbx, bx\n"
  469. "\t\tmov\terrcx, cx\n"
  470. "\n"
  471. "\t\tmov\tax, 3508h\n"
  472. "\t\tint\t21h\n"
  473. "\n"
  474. "\t\tmov\tWORD PTR oldint8h_, bx\n"
  475. "\t\tmov\tWORD PTR oldint8h_ [2], es\n"
  476. "\n"
  477. "\t\tmov\tax, 3509h\n"
  478. "\t\tint\t21h\n"
  479. "\n"
  480. "\t\tmov\tWORD PTR oldint9h_, bx\n"
  481. "\t\tmov\tWORD PTR oldint9h_ [2], es\n"
  482. "\n"
  483. "\t\tmov\tax, 3516h\n"
  484. "\t\tint\t21h\n"
  485. "\n"
  486. "\t\tmov\tWORD PTR oldint16h_, bx\n"
  487. "\t\tmov\tWORD PTR oldint16h_ [2], es\n"
  488. "\n"
  489. "\t\tmov\tax, 351ch\n"
  490. "\t\tint\t21h\n"
  491. "\n"
  492. "\t\tmov\tWORD PTR oldint1ch_, bx\n"
  493. "\t\tmov\tWORD PTR oldint1ch_ [2], es\n"
  494. "\n"
  495. "\t\tlds\tdx, cs:oldint8h\n"
  496. "\t\tmov\tax, 2508h\n"
  497. "\t\tint\t21h\n"
  498. "\n"
  499. "\t\tlds\tdx, cs:oldint9h\n"
  500. "\t\tmov\tax, 2509h\n"
  501. "\t\tint\t21h\n"
  502. "\n"
  503. "\t\tlds\tdx, cs:oldint16h\n"
  504. "\t\tmov\tax, 2516h\n"
  505. "\t\tint\t21h\n"
  506. "\n"
  507. "\t\tlds\tdx, cs:oldint1ch\n"
  508. "\t\tmov\tax, 251ch\n"
  509. "\t\tint\t21h\n"
  510. "\n"
  511. "\t\tpush\tcs\t\t; Restore DS.\n"
  512. "\t\tpop\tds\n"
  513. "launch1:\n"
  514. "\t\tmov\tah, 1\t\t; Remove unwanted keys.\n"
  515. "\t\tint\t16h\n"
  516. "\t\tjz\tlaunch2\n"
  517. "\n"
  518. "\t\tmov\tah, 0\n"
  519. "\t\tint\t16h\n"
  520. "\t\tjmp\tSHORT launch1\n"
  521. "launch2:\n"
  522. "\t\tin\tal, 61h\t\t; Save port value.\n"
  523. "\t\tmov\tport61h, al\n"
  524. "\n"
  525. "\t\tand\tal, 0fch\t; Disconnect speaker.\n"
  526. "\t\tout\t61h, al\n"
  527. "\n"
  528. "\t\tpush\tcs\t\t; Restore ES.\n"
  529. "\t\tpop\tes\n"
  530. "\n"
  531. "\t\tmov\tax, 2\t\t; Hide mouse cursor.\n"
  532. "\t\tint\t33h\n"
  533. "\n"
  534. "\t\tcall\t_main\t\t; Invoke app entry point.\n"
  535. "\n"
  536. "\t\tmov\tax, 1\t\t; Show mouse cursor.\n"
  537. "\t\tint\t33h\n"
  538. "\n"
  539. "\t\tmov\tal, 61h\t\t; Restore port value.\n"
  540. "\t\tout\t61h, al\n"
  541. "\n"
  542. "\t\tpush\tds\n"
  543. "\n"
  544. "\t\tmov\tax, 2508h\n"
  545. "\t\tlds\tdx, cs:oldint8h_\n"
  546. "\t\tint\t21h\n"
  547. "\n"
  548. "\t\tmov\tax, 2509h\n"
  549. "\t\tlds\tdx, cs:oldint9h_\n"
  550. "\t\tint\t21h\n"
  551. "\n"
  552. "\t\tmov\tax, 2516h\n"
  553. "\t\tlds\tdx, cs:oldint16h_\n"
  554. "\t\tint\t21h\n"
  555. "\n"
  556. "\t\tmov\tax, 251ch\n"
  557. "\t\tlds\tdx, cs:oldint1ch_\n"
  558. "\t\tint\t21h\n"
  559. "\n"
  560. "\t\tpop\tds\n"
  561. "\n"
  562. "\t\tmov\tbx, 0\t\t; Must be zero.\n"
  563. "\t\tlea\tdx, errax\t; Point to info structure.\n"
  564. "\t\tmov\tax, 5d0ah\t; Restore extended error info.\n"
  565. "\t\tint\t21h\n"
  566. "\n"
  567. "\t\tlds\tdx, cs:dta\t; Restore DTA.\n"
  568. "\t\tmov\tah, 1ah\n"
  569. "\t\tint\t21h\n"
  570. "\n"
  571. "\t\tmov\tbx, cs:psp_\t; Restore PSP.\n"
  572. "\t\tmov\tah, 50h\n"
  573. "\t\tint\t21h\n"
  574. "\n"
  575. "\t\tlds\tdx, cs:oldint24h\n"
  576. "\t\tmov\tax, 2524h\n"
  577. "\t\tint\t21h\n"
  578. "\n"
  579. "\t\tlds\tdx, cs:oldint23h\n"
  580. "\t\tmov\tax, 2523h\n"
  581. "\t\tint\t21h\n"
  582. "\n"
  583. "\t\tlds\tdx, cs:oldint1bh\n"
  584. "\t\tmov\tax, 251bh\n"
  585. "\t\tint\t21h\n"
  586. "\n"
  587. "\t\tpop\tes\n"
  588. "\t\tpop\tds\n"
  589. "\t\tpop\tbp\n"
  590. "\t\tpop\tdi\n"
  591. "\t\tpop\tsi\n"
  592. "\t\tpop\tdx\n"
  593. "\t\tpop\tcx\n"
  594. "\t\tpop\tbx\n"
  595. "\t\tpop\tax\n"
  596. "\n"
  597. "\t\tcli\t\t\t; Switch stacks.\n"
  598. "\t\tmov\tss, cs:savess\n"
  599. "\t\tmov\tsp, cs:savesp\n"
  600. "\n"
  601. "\t\tret\n"
  602. "launch\t\tENDP\n"
  603. "\n"
  604. "; --------- ;\n"
  605. "; SOUND API ;\n"
  606. "; --------- ;\n"
  607. "\n"
  608. "; ----------------- ;\n"
  609. "; void beep (void); ;\n"
  610. "; ----------------- ;\n"
  611. "\n"
  612. "_beep\t\tPROC\tNEAR\n"
  613. "\t\tpush\tax\n"
  614. "\t\tpush\tbx\n"
  615. "\t\tpush\tcx\n"
  616. "\t\tpush\tdx\n"
  617. "\t\tpush\tds\n"
  618. "\t\tpush\tes\n"
  619. "\n"
  620. "\t\tpush\tcs\n"
  621. "\t\tpop\tds\n"
  622. "\n"
  623. "\t\tmov\tax, 1000\n"
  624. "\t\tpush\tax\n"
  625. "\t\tcall\t_sound\n"
  626. "\t\tpop\tcx\n"
  627. "\n"
  628. "\t\tmov\tax, 6\n"
  629. "\t\tpush\tax\n"
  630. "\t\tcall\t_pause\n"
  631. "\t\tpop\tcx\n"
  632. "\n"
  633. "\t\tcall\t_nosound\n"
  634. "\n"
  635. "\t\tpop\tes\n"
  636. "\t\tpop\tds\n"
  637. "\t\tpop\tdx\n"
  638. "\t\tpop\tcx\n"
  639. "\t\tpop\tbx\n"
  640. "\t\tpop\tax\n"
  641. "\n"
  642. "\t\tret\n"
  643. "_beep\t\tENDP\n"
  644. "\n"
  645. "; -------------------- ;\n"
  646. "; void nosound (void); ;\n"
  647. "; -------------------- ;\n"
  648. "\n"
  649. "_nosound\tPROC\tNEAR\n"
  650. "\t\tin\tal, 61h\t\t; Deactivate sound latch.\n"
  651. "\t\tand\tal, 0fch\n"
  652. "\t\tout\t61h, al\n"
  653. "\n"
  654. "\t\tret\n"
  655. "_nosound\tENDP\n"
  656. "\n"
  657. "; ---------------------------- ;\n"
  658. "; void pause (unsigned ticks); ;\n"
  659. "; ---------------------------- ;\n"
  660. "\n"
  661. "_pause\t\tPROC\tNEAR\n"
  662. "\t\tpush\tbp\n"
  663. "\t\tmov\tbp, sp\n"
  664. "\n"
  665. "\t\tmov\tax, 40h\n"
  666. "\t\tmov\tes, ax\n"
  667. "\n"
  668. "\t\tmov\tax, [bp+4]\t; Get ticks argument.\n"
  669. "\t\tmov\tcx, es:[6ch]\t; Get timer value.\n"
  670. "\t\tadd\tcx, ax\t\t; Compute ending time.\n"
  671. "_pause1:\n"
  672. "\t\tmov\tax, es:[6ch]\t; Get timer value.\n"
  673. "\t\tcmp\tax, cx\t\t; Finished delaying?\n"
  674. "\t\tjnz\t_pause1\t\t; No, branch.\n"
  675. "\n"
  676. "\t\tpop\tbp\n"
  677. "\t\tret\n"
  678. "_pause\t\tENDP\n"
  679. "\n"
  680. "; -------------------------------- ;\n"
  681. "; void sound (unsigned frequency); ;\n"
  682. "; -------------------------------- ;\n"
  683. "\n"
  684. "_sound\t\tPROC\tNEAR\n"
  685. "\t\tpush\tbp\n"
  686. "\t\tmov\tbp, sp\n"
  687. "\n"
  688. "\t\tmov\tbx, [bp+4]\t; Get frequency.\n"
  689. "\t\tmov\tax, 13533\t; Get 1,193,181 into DX:AX.\n"
  690. "\t\tmov\tdx, 18\n"
  691. "\n"
  692. "\t\tcmp\tdx, bx\t\t; Min. frequency must exceed 18 HZ.\n"
  693. "\t\tjnb\t_sound2\t\t; Branch if less.\n"
  694. "\n"
  695. "\t\tdiv\tbx\t\t; Compute 1,193,181/frequency.\n"
  696. "\t\tmov\tbx, ax\n"
  697. "\t\tin\tal, 61h\t\t; Check if sound latch is active.\n"
  698. "\n"
  699. "\t\ttest\tal, 3\t\t; Is sound latch active?\n"
  700. "\t\tjne\t_sound1\t\t; Yes, branch.\n"
  701. "\n"
  702. "\t\tor\tal, 3\t\t; Turn on sound latch.\n"
  703. "\t\tout\t61h, al\n"
  704. "\t\tmov\tal, 0b6h\t; Program 8253 timer channel C.\n"
  705. "\t\tout\t43h, al\n"
  706. "_sound1:\n"
  707. "\t\tmov\tal, bl\t\t; Output division result ...\n"
  708. "\t\tout\t42h, al\t\t; ... to set the frequency.\n"
  709. "\t\tmov\tal, bh\n"
  710. "\t\tout\t42h, al\n"
  711. "_sound2:\n"
  712. "\t\tpop\tbp\n"
  713. "\t\tret\n"
  714. "_sound\t\tENDP\n"
  715. "\n"
  716. "; ------- ;\n"
  717. "; XMS API ;\n"
  718. "; ------- ;\n"
  719. "\n"
  720. "; ----------------------------------------------------- ;\n"
  721. "; XMS_rdriver - redirected device driver for XMS access ;\n"
  722. "; ----------------------------------------------------- ;\n"
  723. "\n"
  724. "XMS_rdriver\tPROC\tFAR\n"
  725. "\t\tmov\tBYTE PTR cs:XMS_inuse, 1\n"
  726. "\t\tcall\tDWORD PTR cs:XMS_driver\n"
  727. "\t\tmov\tBYTE PTR cs:XMS_inuse, 0\n"
  728. "\t\tret\n"
  729. "XMS_rdriver\tENDP\n"
  730. "\n"
  731. "; -------------------------------- ;\n"
  732. "; int XMS_Alloc (unsigned nkilos); ;\n"
  733. "; -------------------------------- ;\n"
  734. "\n"
  735. "_XMS_Alloc\tPROC\tNEAR\n"
  736. "\t\tpush\tbp\n"
  737. "\t\tmov\tbp, sp\n"
  738. "\n"
  739. "\t\tcall\tNEAR PTR _XMS_Exists\n"
  740. "\t\tjz\t_XMS_Alloc1\t; Branch if driver not installed.\n"
  741. "\n"
  742. "\t\tmov\tah, 9\t\t; Allocate extended memory block.\n"
  743. "\t\tmov\tdx, [bp+4]\t; Get number of kilos.\n"
  744. "\t\tcall\tFAR PTR XMS_rdriver\n"
  745. "\n"
  746. "\t\tor\tax, ax\t\t; Error?\n"
  747. "\t\tjz\t_XMS_Alloc1\t; Yes, branch.\n"
  748. "\n"
  749. "\t\tmov\tax, dx\t\t; Return handle.\n"
  750. "_XMS_Alloc1:\n"
  751. "\t\tpop\tbp\n"
  752. "\t\tret\n"
  753. "_XMS_Alloc\tENDP\n"
  754. "\n"
  755. "; ----------------------- ;\n"
  756. "; int XMS_Copy (EMMS *x); ;\n"
  757. "; ----------------------- ;\n"
  758. "\n"
  759. "_XMS_Copy\tPROC\tNEAR\n"
  760. "\t\tpush\tbp\n"
  761. "\t\tmov\tbp, sp\n"
  762. "\n"
  763. "\t\tpush\tsi\n"
  764. "\n"
  765. "\t\tcall\tNEAR PTR _XMS_Exists\n"
  766. "\t\tjz\t_XMS_Copy1\t; Branch if driver not installed.\n"
  767. "\n"
  768. "\t\tmov\tah, 11\t\t; Copy memory block.\n"
  769. "\t\tmov\tsi, [bp+4]\t; Get address of EMMS block.\n"
  770. "\t\tcall\tFAR PTR XMS_rdriver\n"
  771. "_XMS_Copy1:\n"
  772. "\t\tpop\tsi\n"
  773. "\n"
  774. "\t\tpop\tbp\n"
  775. "\t\tret\n"
  776. "_XMS_Copy\tENDP\n"
  777. "\n"
  778. "; ---------------------- ;\n"
  779. "; int XMS_Exists (void); ;\n"
  780. "; ---------------------- ;\n"
  781. "\n"
  782. "_XMS_Exists\tPROC\tNEAR\n"
  783. "\t\tmov\tax, WORD PTR XMS_driver\n"
  784. "\t\tor\tax, WORD PTR XMS_driver [2]\n"
  785. "\t\tret\n"
  786. "_XMS_Exists\tENDP\n"
  787. "\n"
  788. "; ------------------------------- ;\n"
  789. "; int XMS_Free (unsigned handle); ;\n"
  790. "; ------------------------------- ;\n"
  791. "\n"
  792. "_XMS_Free\tPROC\tNEAR\n"
  793. "\t\tpush\tbp\n"
  794. "\t\tmov\tbp, sp\n"
  795. "\n"
  796. "\t\tcall\tNEAR PTR _XMS_Exists\n"
  797. "\t\tjz\t_XMS_Free1\t; Branch if driver not installed.\n"
  798. "\n"
  799. "\t\tmov\tah, 10\t\t; Free extended memory block.\n"
  800. "\t\tmov\tdx, [bp+4]\t; Get handle.\n"
  801. "\t\tcall\tFAR PTR XMS_rdriver\n"
  802. "_XMS_Free1:\n"
  803. "\t\tpop\tbp\n"
  804. "\t\tret\n"
  805. "_XMS_Free\tENDP\n"
  806. "\n"
  807. "; -------------------------------- ;\n"
  808. "; long XMS_Lock (unsigned handle); ;\n"
  809. "; -------------------------------- ;\n"
  810. "\n"
  811. "_XMS_Lock\tPROC\tNEAR\n"
  812. "\t\tpush\tbp\n"
  813. "\t\tmov\tbp, sp\n"
  814. "\n"
  815. "\t\tcall\tNEAR PTR _XMS_Exists\n"
  816. "\t\tjz\t_XMS_Lock1\t; Branch if driver not installed.\n"
  817. "\n"
  818. "\t\tmov\tah, 12\t\t; Lock extended memory block.\n"
  819. "\t\tmov\tdx, [bp+4]\t; Get handle.\n"
  820. "\t\tcall\tFAR PTR XMS_rdriver\n"
  821. "\n"
  822. "\t\tor\tax, ax\t\t; Error?\n"
  823. "\t\tjz\t_XMS_Lock1\t; Yes, branch.\n"
  824. "\n"
  825. "\t\tmov\tax, bx\t\t; Finish computing 32-bit address.\n"
  826. "\t\tjmp\tSHORT _XMS_Lock2\n"
  827. "_XMS_Lock1:\n"
  828. "\t\txor\tdx, dx\n"
  829. "_XMS_Lock2:\n"
  830. "\t\tpop\tbp\n"
  831. "\t\tret\n"
  832. "_XMS_Lock\tENDP\n"
  833. "\n"
  834. "; --------------------------------------------------------- ;\n"
  835. "; int XMS_Query (unsigned *nkilos, unsigned *maxblocksize); ;\n"
  836. "; --------------------------------------------------------- ;\n"
  837. "\n"
  838. "_XMS_Query\tPROC\tNEAR\n"
  839. "\t\tpush\tbp\n"
  840. "\t\tmov\tbp, sp\n"
  841. "\n"
  842. "\t\tcall\tNEAR PTR _XMS_Exists\n"
  843. "\t\tjz\t_XMS_Query1\t; Branch if driver not installed.\n"
  844. "\n"
  845. "\t\tmov\tah, 8\t\t; Query free extended memory.\n"
  846. "\t\tcall\tFAR PTR XMS_rdriver\n"
  847. "\n"
  848. "\t\tor\tax, ax\t\t; Error?\n"
  849. "\t\tjz\t_XMS_Query1\t; Yes, branch.\n"
  850. "\n"
  851. "\t\tmov\tbx, [bp+4]\t; Save number of kilobytes.\n"
  852. "\t\tmov\t[bx], ax\n"
  853. "\n"
  854. "\t\tmov\tbx, [bp+6]\t; Save largest block size.\n"
  855. "\t\tmov\t[bx], dx\n"
  856. "_XMS_Query1:\n"
  857. "\t\tpop\tbp\n"
  858. "\t\tret\n"
  859. "_XMS_Query\tENDP\n"
  860. "\n"
  861. "; --------------------------------------------------- ;\n"
  862. "; int XMS_Realloc (unsigned handle, unsigned nkilos); ;\n"
  863. "; --------------------------------------------------- ;\n"
  864. "\n"
  865. "_XMS_ReAlloc\tPROC\tNEAR\n"
  866. "\t\tpush\tbp\n"
  867. "\t\tmov\tbp, sp\n"
  868. "\n"
  869. "\t\tcall\tNEAR PTR _XMS_Exists\n"
  870. "\t\tjz\t_XMS_Realloc1\t; Branch if driver not installed.\n"
  871. "\n"
  872. "\t\tmov\tah, 15\t\t; Reallocate extended memory block.\n"
  873. "\t\tmov\tbx, [bp+6]\t; Get new memory length in kilos.\n"
  874. "\t\tmov\tdx, [bp+4]\t; Get handle.\n"
  875. "\t\tcall\tFAR PTR XMS_rdriver\n"
  876. "_XMS_Realloc1:\n"
  877. "\t\tpop\tbp\n"
  878. "\t\tret\n"
  879. "_XMS_Realloc\tENDP\n"
  880. "\n"
  881. "; --------------------------------- ;\n"
  882. "; int XMS_Unlock (unsigned handle); ;\n"
  883. "; --------------------------------- ;\n"
  884. "\n"
  885. "_XMS_Unlock\tPROC\tNEAR\n"
  886. "\t\tpush\tbp\n"
  887. "\t\tmov\tbp, sp\n"
  888. "\n"
  889. "\t\tcall\tNEAR PTR _XMS_Exists\n"
  890. "\t\tjz\t_XMS_Unlock1\t; Branch if driver not installed.\n"
  891. "\n"
  892. "\t\tmov\tah, 13\t\t; Unlock extended memory block.\n"
  893. "\t\tmov\tdx, [bp+4]\t; Get handle.\n"
  894. "\t\tcall\tFAR PTR XMS_rdriver\n"
  895. "_XMS_Unlock1:\n"
  896. "\t\tpop\tbp\n"
  897. "\t\tret\n"
  898. "_XMS_Unlock\tENDP\n\n";
  899.  
  900. /* --------------------------------------------------------------------- */
  901.  
  902. char *listing5 =
  903.  
  904. "\n"
  905. "; ------------------------- ;\n"
  906. "; Installation Data Section ;\n"
  907. "; ------------------------- ;\n"
  908. "\n"
  909. "installsec:\n"
  910. "\n"
  911. "ctailaddr\tDW\t81h\t\t; Command tail address.\n"
  912. "psp\t\tDW\t?\t\t; PSP of \"searched\" TSR.\n"
  913. "\n"
  914. "scancodes\tDB\t30,48,46,32,18,33,34,35,23,36,37,38,50 ; A-M\n"
  915. "\t\tDB\t49,24,25,16,19,31,20,22,47,17,45,21,44 ; N-Z\n"
  916. "\t\tDB\t11,02,03,04,05,06,07,08,09,10          ; 0-9\n"
  917. "\n"
  918. "tsr_delmsg\tDB\tCR, LF\n"
  919. "\t\tDB\t\"successfully uninstalled\"\n"
  920. "\t\tDB\tCR, LF\n"
  921. "\t\tDB\t'$'\n"
  922. "\n"
  923. "tsr_keymsg\tDB\tCR, LF\n"
  924. "\t\tDB\t\"hotkey = ALT-\"\n"
  925. "tsr_keymsg1\tDB\t?\n"
  926. "\t\tDB\tCR, LF\n"
  927. "\t\tDB\t'$'\n"
  928. "\n"
  929. "tsr_errmsg1\tDB\tCR, LF\n"
  930. "\t\tDB\t\"invalid DOS version (must be 3.30 or higher)\"\n"
  931. "\t\tDB\tCR, LF\n"
  932. "\t\tDB\t'$'\n"
  933. "\n"
  934. "tsr_errmsg2\tDB\tCR, LF\n"
  935. "\t\tDB\t\"invalid character on command line\"\n"
  936. "\t\tDB\tCR, LF\n"
  937. "\t\tDB\t'$'\n"
  938. "\n"
  939. "tsr_errmsg3\tDB\tCR, LF\n"
  940. "\t\tDB\t\"invalid option\"\n"
  941. "\t\tDB\tCR, LF\n"
  942. "\t\tDB\t'$'\n"
  943. "\n"
  944. "tsr_errmsg4\tDB\tCR, LF\n"
  945. "\t\tDB\t\"not in memory\"\n"
  946. "\t\tDB\tCR, LF\n"
  947. "\t\tDB\t'$'\n"
  948. "\n"
  949. "tsr_errmsg5\tDB\tCR, LF\n"
  950. "\t\tDB\t\"unable to uninstall\"\n"
  951. "\t\tDB\tCR, LF\n"
  952. "\t\tDB\t'$'\n"
  953. "\n"
  954. "tsr_errmsg6\tDB\tCR, LF\n"
  955. "\t\tDB\t\"invalid hotkey character\"\n"
  956. "\t\tDB\tCR, LF\n"
  957. "\t\tDB\t'$'\n"
  958. "\n";
  959.  
  960. /* --------------------------------------------------------------------- */
  961.  
  962. char *listing6 =
  963.  
  964. "tsr_errmsg7\tDB\tCR, LF\n"
  965. "\t\tDB\t\"unable to setup\"\n"
  966. "\t\tDB\tCR, LF\n"
  967. "\t\tDB\t'$'\n"
  968. "\n";
  969.  
  970. /* --------------------------------------------------------------------- */
  971.  
  972. char *listing7 =
  973.  
  974. "tsr_errmsg8\tDB\tCR, LF\n"
  975. "\t\tDB\t\"unable to completely uninstall * \"\n"
  976. "\t\tDB\t\"system unstable * please reboot\"\n"
  977. "\t\tDB\tCR, LF\n"
  978. "\t\tDB\t'$'\n"
  979. "\n"
  980. "ver\t\tDB\t?\t\t; Major portion of DOS version.\n"
  981. "\n"
  982. "; ------------------------- ;\n"
  983. "; Installation Code Section ;\n"
  984. "; ------------------------- ;\n"
  985. "\n"
  986. "install:\n"
  987. "\t\tlea\tbx, _title\t; Display suitable title.\n"
  988. "\t\tmov\tdx, [bx]\n"
  989. "\t\tmov\tah, 9\n"
  990. "\t\tint\t21h\n"
  991. "\n"
  992. "\t\tmov\tah, 30h\t\t; Obtain DOS version number.\n"
  993. "\t\tint\t21h\n"
  994. "\n"
  995. "\t\tcmp\tal, 3\t\t; Test major portion.\n"
  996. "\t\tjb\tinstall1\t; Branch if less that 3.\n"
  997. "\t\tja\tinstall2\t; Branch if greater than 3.\n"
  998. "\n"
  999. "\t\tcmp\tah, 30\t\t; Test minor portion.\n"
  1000. "\t\tjae\tinstall2\t; Branch if >= 30.\n"
  1001. "install1:\n"
  1002. "\t\tlea\tdx, tsr_errmsg1\t; Display error message.\n"
  1003. "\t\tmov\tah, 9\n"
  1004. "\t\tint\t21h\n"
  1005. "\n"
  1006. "\t\tmov\tax, 4c01h\t; Exit with error code 1.\n"
  1007. "\t\tint\t21h\n"
  1008. "install2:\n"
  1009. "\t\tmov\tver, al\t\t; Save major portion of version.\n"
  1010. "\n"
  1011. "\t\tmov\tax, 5d06h\t; Obtain critical error flag.\n"
  1012. "\t\tint\t21h\n"
  1013. "\n"
  1014. "\t\tmov\tax, ds\n"
  1015. "\n"
  1016. "\t\tpush\tcs\t\t; Restore DS.\n"
  1017. "\t\tpop\tds\n"
  1018. "\n"
  1019. "\t\tmov\tWORD PTR criterr, si\n"
  1020. "\t\tmov\tWORD PTR criterr [2], ax\n"
  1021. "\n"
  1022. "\t\tmov\tah, 34h\t\t; Obtain critical section flag.\n"
  1023. "\t\tint\t21h\n"
  1024. "\n"
  1025. "\t\tmov\tWORD PTR critsec, bx\n"
  1026. "\t\tmov\tWORD PTR critsec [2], es\n"
  1027. "\n"
  1028. "\t\tpush\tcs\n"
  1029. "\t\tpop\tes\n"
  1030. "\n"
  1031. "\t\tlea\tbx, signature\t; Search for resident copy.\n"
  1032. "\t\tnot\tBYTE PTR [bx]\t; Avoid false cache match.\n"
  1033. "\t\tmov\tcx, SIGLENGTH\t; Get length of signature.\n"
  1034. "\t\tcall\tsearch\t\t; Search for prior copy.\n"
  1035. "\t\tmov\tpsp, ax\t\t; Save PSP of prior/current TSR.\n"
  1036. "install3:\n"
  1037. "\t\tcall\t_skipws\t\t; Skip whitespace.\n"
  1038. "\t\tcall\t_parse\t\t; Parse nonwhitespace character.\n"
  1039. "\n"
  1040. "\t\tcmp\tal, CR\t\t; End of command tail?\n"
  1041. "\t\tjnz\tinstall4\t; No, branch.\n"
  1042. "\n"
  1043. "\t\tmov\tax, psp\t\t; Point ES to resident or ...\n"
  1044. "\t\tmov\tes, ax\t\t; ... current segment.\n"
  1045. "\n"
  1046. "\t\tmov\tal, es:key\t; Get hotkey character.\n"
  1047. "\t\tmov\ttsr_keymsg1, al\n"
  1048. "\n"
  1049. "\t\tpush\tcs\t\t; Restore ES if necessary.\n"
  1050. "\t\tpop\tes\n"
  1051. "\n"
  1052. "\t\tlea\tdx, tsr_keymsg\t; Display hotkey message.\n"
  1053. "\t\tmov\tah, 9\n"
  1054. "\t\tint\t21h\n"
  1055. "\n"
  1056. "\t\tmov\tax, cs\t\t; First install?\n"
  1057. "\t\tcmp\tax, psp\n"
  1058. "\t\tjz\tinstall10\t; Yes, branch.\n"
  1059. "\n"
  1060. "\t\tmov\tax, 4c00h\t; Exit with OK code.\n"
  1061. "\t\tint\t21h\n"
  1062. "install4:\n"
  1063. "\t\tcmp\tal, '/'\t\t; Option?\n"
  1064. "\t\tjz\tinstall5\t; Yes, branch.\n"
  1065. "\n"
  1066. "\t\tlea\tdx, tsr_errmsg2\t; Display error message.\n"
  1067. "\t\tmov\tah, 9\n"
  1068. "\t\tint\t21h\n"
  1069. "\n"
  1070. "\t\tmov\tax, 4c01h\t; Exit with error code 1.\n"
  1071. "\t\tint\t21h\n"
  1072. "install5:\n"
  1073. "\t\tcall\t_parse\t\t; Extract next character.\n"
  1074. "\t\tcall\tupper\t\t; Convert to uppercase.\n"
  1075. "\n"
  1076. "\t\tcmp\tal, 'B'\t\t; Beep option?\n"
  1077. "\t\tjnz\tinstall6\t; No, branch.\n"
  1078. "\n"
  1079. "\t\tcall\tparse_beep\t; Parse beep option.\n"
  1080. "\t\tjmp\tSHORT install3\n"
  1081. "install6:\n"
  1082. "\t\tcmp\tal, 'K'\t\t; Hotkey option?\n"
  1083. "\t\tjnz\tinstall7\t; No, branch.\n"
  1084. "\n"
  1085. "\t\tcall\tparse_key\t; Parse hotkey option.\n"
  1086. "\t\tjmp\tSHORT install3\n"
  1087. "install7:\n"
  1088. "\t\tcmp\tal, 'U'\t\t; Uninstall option?\n"
  1089. "\t\tjnz\tinstall9\t; No, branch.\n"
  1090. "\n"
  1091. "\t\tmov\tax, cs\t\t; First install?\n"
  1092. "\t\tcmp\tax, psp\n"
  1093. "\t\tjnz\tinstall8\t; No, branch.\n"
  1094. "\n"
  1095. "\t\tlea\tdx, tsr_errmsg4\t; Display error message.\n"
  1096. "\t\tmov\tah, 9\n"
  1097. "\t\tint\t21h\n"
  1098. "\n"
  1099. "\t\tmov\tax, 4c01h\t; Exit with error code 1.\n"
  1100. "\t\tint\t21h\n"
  1101. "install8:\n"
  1102. "\t\tjmp\tuninstall\n"
  1103. "install9:\n";
  1104.  
  1105. /* --------------------------------------------------------------------- */
  1106.  
  1107. char *listing8_1 =
  1108.  
  1109. "\t\tpush\tax\n"
  1110. "\t\tcall\t_xparse\t\t; Extended parsing.\n"
  1111. "\t\tpop\tcx\n"
  1112. "\n"
  1113. "\t\tor\tax, ax\t\t; Parse error?\n"
  1114. "\t\tjz\tinstall3\t; No, branch.\n"
  1115. "\n";
  1116.  
  1117. /* --------------------------------------------------------------------- */
  1118.  
  1119. char *listing8_2 =
  1120.  
  1121. "\t\tlea\tdx, tsr_errmsg3\t; Display error message.\n"
  1122. "\t\tmov\tah, 9\n"
  1123. "\t\tint\t21h\n"
  1124. "\n"
  1125. "\t\tmov\tax, 4c01h\t; Exit with error code 1.\n"
  1126. "\t\tint\t21h\n"
  1127. "install10:\n";
  1128.  
  1129. /* --------------------------------------------------------------------- */
  1130.  
  1131. char *listing9 =
  1132.  
  1133. "\t\tcall\t_setup\t\t; Attempt additional setup.\n"
  1134. "\n"
  1135. "\t\tor\tax, ax\t\t; Setup successful?\n"
  1136. "\t\tjz\tinstall11\t; Yes, branch.\n"
  1137. "\n"
  1138. "\t\tlea\tdx, tsr_errmsg7\t; Display error message.\n"
  1139. "\t\tmov\tah, 9\n"
  1140. "\t\tint\t21h\n"
  1141. "\n"
  1142. "\t\tmov\tax, 4c01h\t; Exit with error code 1.\n"
  1143. "\t\tint\t21h\n"
  1144. "install11:\n";
  1145.  
  1146. /* --------------------------------------------------------------------- */
  1147.  
  1148. char *listing10 =
  1149.  
  1150. "\t\tcmp\tBYTE PTR ver, 5\t; Version number at least 5.0?\n"
  1151. "\t\tjb\tinstall11_5\t; No, branch.\n"
  1152. "\n"
  1153. "\t\tmov\tax, 4300h\t; Get HIMEM.SYS installed state.\n"
  1154. "\t\tint\t2fh\n"
  1155. "\n"
  1156. "\t\tor\tal, al\t\t; Installed?\n"
  1157. "\t\tjz\tinstall11_5\t; No, branch.\n"
  1158. "\n"
  1159. "\t\tmov\tax, 4310h\t; Get entry point address.\n"
  1160. "\t\tint\t2fh\n"
  1161. "\n"
  1162. "\t\tmov\tWORD PTR XMS_driver, bx\n"
  1163. "\t\tmov\tWORD PTR XMS_driver [2], es\n"
  1164. "install11_5:\n"
  1165. "\t\tmov\tax, 3508h\t; Get timer hard interrupt vector.\n"
  1166. "\t\tint\t21h\n"
  1167. "\n"
  1168. "\t\tmov\tWORD PTR oldint8h, bx\n"
  1169. "\t\tmov\tWORD PTR oldint8h [2], es\n"
  1170. "\n"
  1171. "\t\tmov\tax, 3509h\t; Get key hard interrupt vector.\n"
  1172. "\t\tint\t21h\n"
  1173. "\n"
  1174. "\t\tmov\tWORD PTR oldint9h, bx\n"
  1175. "\t\tmov\tWORD PTR oldint9h [2], es\n"
  1176. "\n"
  1177. "\t\tmov\tax, 3513h\t; Get disk interrupt vector.\n"
  1178. "\t\tint\t21h\n"
  1179. "\n"
  1180. "\t\tmov\tWORD PTR oldint13h, bx\n"
  1181. "\t\tmov\tWORD PTR oldint13h [2], es\n"
  1182. "\n"
  1183. "\t\tmov\tax, 3516h\t; Get key soft interrupt vector.\n"
  1184. "\t\tint\t21h\n"
  1185. "\n"
  1186. "\t\tmov\tWORD PTR oldint16h, bx\n"
  1187. "\t\tmov\tWORD PTR oldint16h [2], es\n"
  1188. "\n"
  1189. "\t\tmov\tax, 351ch\t; Get timer soft interrupt vector.\n"
  1190. "\t\tint\t21h\n"
  1191. "\n"
  1192. "\t\tmov\tWORD PTR oldint1ch, bx\n"
  1193. "\t\tmov\tWORD PTR oldint1ch [2], es\n"
  1194. "\n"
  1195. "\t\tmov\tax, 3528h\t; Get idle interrupt vector.\n"
  1196. "\t\tint\t21h\n"
  1197. "\n"
  1198. "\t\tmov\tWORD PTR oldint28h, bx\n"
  1199. "\t\tmov\tWORD PTR oldint28h [2], es\n"
  1200. "\n"
  1201. "\t\tmov\tax, 352fh\t; Get mux interrupt vector.\n"
  1202. "\t\tint\t21h\n"
  1203. "\n"
  1204. "\t\tmov\tWORD PTR oldint2fh, bx\n"
  1205. "\t\tmov\tWORD PTR oldint2fh [2], es\n"
  1206. "\n"
  1207. "\t\tmov\tax, ds:[002ch]\t; Attempt to free environment.\n"
  1208. "\t\tcmp\tax, 0\t\t; Can we free environment?\n"
  1209. "\t\tjz\tinstall12\t; No, branch.\n"
  1210. "\n"
  1211. "\t\tmov\tes, ax\t    ; Free environment block.\n"
  1212. "\t\tmov\tah, 49h\n"
  1213. "\t\tint\t21h\n"
  1214. "\n"
  1215. "\t\tmov\tWORD PTR ds:[002ch], 0\t; Indicate no environment.\n"
  1216. "install12:\n"
  1217. "\t\tmov\tax, 2508h\t; Set new timer interrupt vector.\n"
  1218. "\t\tlea\tdx, newint8h\n"
  1219. "\t\tint\t21h\n"
  1220. "\n"
  1221. "\t\tmov\tax, 2513h\t; Set new disk interrupt vector.\n"
  1222. "\t\tlea\tdx, newint13h\n"
  1223. "\t\tint\t21h\n"
  1224. "\n"
  1225. "\t\tmov\tax, 2528h\t; Set new idle interrupt vector.\n"
  1226. "\t\tlea\tdx, newint28h\n"
  1227. "\t\tint\t21h\n"
  1228. "\n"
  1229. "\t\tmov\tax, 252fh\t; Set new mux interrupt vector.\n"
  1230. "\t\tlea\tdx, newint2fh\n"
  1231. "\t\tint\t21h\n"
  1232. "\n"
  1233. "\t\tmov\tax, 2509h\t; Set new key interrupt vector.\n"
  1234. "\t\tlea\tdx, newint9h\n"
  1235. "\t\tint\t21h\n"
  1236. "\n"
  1237. "\t\tlea\tdx, installsec\t; Calculate number of para- ...\n"
  1238. "\t\tadd\tdx, 15\t\t; ... graphs to keep resident.\n"
  1239. "\t\tmov\tcl, 4\n"
  1240. "\t\tshr\tdx, cl\n"
  1241. "\n"
  1242. "\t\tmov\tax, 3100h\t; TSR.\n"
  1243. "\t\tint\t21h\n"
  1244. "\n"
  1245. "; -------------------- ;\n"
  1246. "; Installation Support ;\n"
  1247. "; -------------------- ;\n"
  1248. "\n"
  1249. "; ---------------------------------------------- ;\n"
  1250. "; Convert: Convert hotkey character to scancode. ;\n"
  1251. ";                                                ;\n"
  1252. "; Entry: AL = character ('A'-'Z' or '0'-'9')     ;\n"
  1253. ";                                                ;\n"
  1254. "; Exit:  AL = scancode                           ;\n"
  1255. ";                                                ;\n"
  1256. "; All other registers preserved.                 ;\n"
  1257. "; Requires presence of scancodes array.          ;\n"
  1258. "; ---------------------------------------------- ;\n"
  1259. "\n"
  1260. "convert\t\tPROC\tNEAR\n"
  1261. "\t\tpush\tbx\n"
  1262. "\n"
  1263. "\t\tmov\tbl, al\t\t; Get hotkey character.\n"
  1264. "\t\txor\tbh, bh\n"
  1265. "\n"
  1266. "\t\tcmp\tbl, 'A'\t\t; Alphabetic hotkey?\n"
  1267. "\t\tjb\tconvert1\t; No, branch.\n"
  1268. "\n"
  1269. "\t\tsub\tbl, 'A'\t\t; Get alphabetic scancode.\n"
  1270. "\t\tmov\tal, scancodes [bx]\n"
  1271. "\n"
  1272. "\t\tpop\tbx\n"
  1273. "\n"
  1274. "\t\tret\n"
  1275. "convert1:\n"
  1276. "\t\tsub\tbl, '0'\t\t; Get digit scancode.\n"
  1277. "\t\tmov\tal, scancodes [bx+26]\n"
  1278. "\n"
  1279. "\t\tpop\tbx\n"
  1280. "\n"
  1281. "\t\tret\n"
  1282. "convert\t\tENDP\n"
  1283. "\n"
  1284. "; ------------------------------------- ;\n"
  1285. "; Parse: Parse nonwhitespace character. ;\n"
  1286. ";                                       ;\n"
  1287. "; Entry: none                           ;\n"
  1288. ";                                       ;\n"
  1289. "; Exit: AX = character                  ;\n"
  1290. ";                                       ;\n"
  1291. "; All other registers preserved.        ;\n"
  1292. "; ------------------------------------- ;\n"
  1293. "\n"
  1294. "_parse\t\tPROC\tNEAR\n"
  1295. "\t\tpush\tbx\n"
  1296. "\n"
  1297. "\t\tmov\tbx, ctailaddr\t; Get command tail address.\n"
  1298. "\t\tmov\tal, [bx]\t; Get character at this address.\n"
  1299. "\t\tmov\tah, 0\n"
  1300. "\n"
  1301. "\t\tcmp\tal, CR\t\t; End of command tail?\n"
  1302. "\t\tjz\tparse1\t\t; Yes, branch.\n"
  1303. "\n"
  1304. "\t\tinc\tbx\t\t; Point to next character.\n"
  1305. "\t\tmov\tctailaddr, bx\t; Update command tail address.\n"
  1306. "parse1:\n"
  1307. "\t\tpop\tbx\n"
  1308. "\n"
  1309. "\t\tret\n"
  1310. "_parse\t\tENDP\n"
  1311. "\n"
  1312. "; --------------------------- ;\n"
  1313. "; Parse_beep: Parse B option. ;\n"
  1314. ";                             ;\n"
  1315. "; Entry: none                 ;\n"
  1316. ";                             ;\n"
  1317. "; Exit: none                  ;\n"
  1318. ";                             ;\n"
  1319. "; All registers preserved.    ;\n"
  1320. "; --------------------------- ;\n"
  1321. "\n"
  1322. "parse_beep\tPROC\tNEAR\n"
  1323. "\t\tpush\tax\n"
  1324. "\t\tpush\tes\n"
  1325. "\n"
  1326. "\t\tcall\t_parse\t\t; Parse character after B.\n"
  1327. "\n"
  1328. "\t\tcmp\tal, '0'\t\t; Disable beeping?\n"
  1329. "\t\tjb\tparse_beep1\t; No, branch.\n"
  1330. "\n"
  1331. "\t\tcmp\tal, '1'\t\t; Disable or enable beeping?\n"
  1332. "\t\tjbe\tparse_beep2\t; Yes, branch.\n"
  1333. "parse_beep1:\n"
  1334. "\t\tlea\tdx, tsr_errmsg3\t; Display error message.\n"
  1335. "\t\tmov\tah, 9\n"
  1336. "\t\tint\t21h\n"
  1337. "\n"
  1338. "\t\tpop\tes\t\t; Cleanup stack even though ...\n"
  1339. "\t\tpop\tax\t\t; ... we don't have to.\n"
  1340. "\n"
  1341. "\t\tmov\tax, 4c01h\t; Exit with error code 1.\n"
  1342. "\t\tint\t21h\n"
  1343. "parse_beep2:\n"
  1344. "\t\tpush\tax\n"
  1345. "\n"
  1346. "\t\tmov\tax, psp\t\t; Point ES to resident segment.\n"
  1347. "\t\tmov\tes, ax\n"
  1348. "\n"
  1349. "\t\tpop\tax\n"
  1350. "\n"
  1351. "\t\tsub\tal, '0'\t\t; Convert ASCII to binary.\n"
  1352. "\t\tmov\tes:beepf, al\t; Save character.\n"
  1353. "\n"
  1354. "\t\tpop\tes\n"
  1355. "\t\tpop\tax\n"
  1356. "\n"
  1357. "\t\tret\n"
  1358. "parse_beep\tENDP\n"
  1359. "\n"
  1360. "; -------------------------- ;\n"
  1361. "; Parse_key: Parse K option. ;\n"
  1362. ";                            ;\n"
  1363. "; Entry: none                ;\n"
  1364. ";                            ;\n"
  1365. "; Exit: none                 ;\n"
  1366. ";                            ;\n"
  1367. "; All registers preserved.   ;\n"
  1368. "; -------------------------- ;\n"
  1369. "\n"
  1370. "parse_key\tPROC\tNEAR\n"
  1371. "\t\tpush\tax\n"
  1372. "\t\tpush\tes\n"
  1373. "\n"
  1374. "\t\tcall\t_parse\t\t; Parse character after K.\n"
  1375. "\n"
  1376. "\t\tcmp\tal, 'a'\t\t; Convert to uppercase.\n"
  1377. "\t\tjb\tparse_key1\n"
  1378. "\n"
  1379. "\t\tcmp\tal, 'z'\n"
  1380. "\t\tja\tparse_key1\n"
  1381. "\n"
  1382. "\t\tsub\tal, 32\n"
  1383. "parse_key1:\n"
  1384. "\t\tcmp\tal, '0'\t\t; Validate.\n"
  1385. "\t\tjb\tparse_key2\n"
  1386. "\n"
  1387. "\t\tcmp\tal, 'Z'\n"
  1388. "\t\tja\tparse_key2\n"
  1389. "\n"
  1390. "\t\tcmp\tal, '9'\n"
  1391. "\t\tjbe\tparse_key3\n"
  1392. "\n"
  1393. "\t\tcmp\tal, 'A'\n"
  1394. "\t\tjae\tparse_key3\n"
  1395. "parse_key2:\n"
  1396. "\t\tlea\tdx, tsr_errmsg6\t; Display error message.\n"
  1397. "\t\tmov\tah, 9\n"
  1398. "\t\tint\t21h\n"
  1399. "\n"
  1400. "\t\tpop\tes\t\t; Cleanup stack even though ...\n"
  1401. "\t\tpop\tax\t\t; ... we don't have to.\n"
  1402. "\n"
  1403. "\t\tmov\tax, 4c01h\t; Exit with error code 1.\n"
  1404. "\t\tint\t21h\n"
  1405. "parse_key3:\n"
  1406. "\t\tpush\tax\n"
  1407. "\n"
  1408. "\t\tmov\tax, psp\t\t; Point ES to resident segment.\n"
  1409. "\t\tmov\tes, ax\n"
  1410. "\n"
  1411. "\t\tpop\tax\n"
  1412. "\n"
  1413. "\t\tmov\tes:key, al\t; Save character.\n"
  1414. "\n"
  1415. "\t\tcall\tconvert\t\t; Convert character to scancode.\n"
  1416. "\n"
  1417. "\t\tmov\tes:scancode, al\t; Save scancode.\n"
  1418. "\n"
  1419. "\t\tpop\tes\n"
  1420. "\t\tpop\tax\n"
  1421. "\n"
  1422. "\t\tret\n"
  1423. "parse_key\tENDP\n"
  1424. "\n"
  1425. "; ------------------------------------------------ ;\n"
  1426. "; Search: Search memory for previous TSR copy.     ;\n"
  1427. ";                                                  ;\n"
  1428. "; Entry: BX = address of signature to search       ;\n"
  1429. ";        CX = length of signature                  ;\n"
  1430. ";                                                  ;\n"
  1431. "; Exit:  AX = PSP address of prior or current copy ;\n"
  1432. ";                                                  ;\n"
  1433. "; All registers preserved (direction flag cleared) ;\n"
  1434. "; ------------------------------------------------ ;\n"
  1435. "\n"
  1436. "search\t\tPROC\tNEAR\n"
  1437. "\t\tpush\tbx\n"
  1438. "\t\tpush\tcx\n"
  1439. "\t\tpush\tsi\n"
  1440. "\t\tpush\tdi\n"
  1441. "\t\tpush\tes\n"
  1442. "\n"
  1443. "\t\tmov\tsi, bx\t\t; SI will point to signature.\n"
  1444. "\n"
  1445. "\t\tmov\tax, 0a000h\t; Initial segment.\n"
  1446. "\t\tmov\tbx, cs\t\t; Final segment.\n"
  1447. "\t\tcld\t\t\t; Forward string operations.\n"
  1448. "search1:\n"
  1449. "\t\tinc\tax\t\t; Point to next segment.\n"
  1450. "\n"
  1451. "\t\tcmp\tax, bx\t\t; At current segment?\n"
  1452. "\t\tjz\tsearch2\t\t; Yes, exit search.\n"
  1453. "\n"
  1454. "\t\tmov\tes, ax\t\t; Target segment.\n"
  1455. "\t\tmov\tdi, si\t\t; Same offset.\n"
  1456. "\n"
  1457. "\t\tpush\tcx\t\t; CMPSB destroys CX and SI.\n"
  1458. "\t\tpush\tsi\n"
  1459. "\n"
  1460. "\t\trep\tcmpsb\t\t; Search for match.\n"
  1461. "\n"
  1462. "\t\tpop\tsi\n"
  1463. "\t\tpop\tcx\n"
  1464. "\n"
  1465. "\t\tjnz\tsearch1\t\t; Branch if no match.\n"
  1466. "search2:\n"
  1467. "\t\tpop\tes\n"
  1468. "\t\tpop\tdi\n"
  1469. "\t\tpop\tsi\n"
  1470. "\t\tpop\tcx\n"
  1471. "\t\tpop\tbx\n"
  1472. "\n"
  1473. "\t\tret\n"
  1474. "search\t\tENDP\n"
  1475. "\n"
  1476. "; --------------------------------------- ;\n"
  1477. "; Setcseg: Set DS and ES regs to cur seg. ;\n"
  1478. ";                                         ;\n"
  1479. "; Entry: none                             ;\n"
  1480. ";                                         ;\n"
  1481. "; Exit: none                              ;\n"
  1482. ";                                         ;\n"
  1483. "; All registers preserved.                ;\n"
  1484. "; --------------------------------------- ;\n"
  1485. "\n"
  1486. "_setcseg\tPROC\tNEAR\n"
  1487. "\t\tpush\tcs\n"
  1488. "\t\tpop\tds\n"
  1489. "\n"
  1490. "\t\tpush\tcs\n"
  1491. "\t\tpop\tes\n"
  1492. "\n"
  1493. "\t\tret\n"
  1494. "_setcseg\tENDP\n"
  1495. "\n"
  1496. "; --------------------------------------- ;\n"
  1497. "; Setrseg: Set DS and ES regs to res seg. ;\n"
  1498. ";                                         ;\n"
  1499. "; Entry: none                             ;\n"
  1500. ";                                         ;\n"
  1501. "; Exit: none                              ;\n"
  1502. ";                                         ;\n"
  1503. "; All registers preserved.                ;\n"
  1504. "; --------------------------------------- ;\n"
  1505. "\n"
  1506. "_setrseg\tPROC\tNEAR\n"
  1507. "\t\tmov\tds, psp\n"
  1508. "\t\tmov\tes, psp\n"
  1509. "\n"
  1510. "\t\tret\n"
  1511. "_setrseg\tENDP\n"
  1512. "\n"
  1513. "; ---------------------------------------- ;\n"
  1514. "; Skipws: Skip whitespace on command tail. ;\n"
  1515. ";                                          ;\n"
  1516. "; Entry: none                              ;\n"
  1517. ";                                          ;\n"
  1518. "; Exit: none                               ;\n"
  1519. ";                                          ;\n"
  1520. "; All registers preserved.                 ;\n"
  1521. "; ---------------------------------------- ;\n"
  1522. "\n"
  1523. "_skipws\t\tPROC\tNEAR\n"
  1524. "\t\tpush\tax\n"
  1525. "\t\tpush\tbx\n"
  1526. "\n"
  1527. "\t\tmov\tbx, ctailaddr\t; Get command tail address.\n"
  1528. "skipws1:\n"
  1529. "\t\tmov\tal, [bx]\t; Get command tail character.\n"
  1530. "\n"
  1531. "\t\tcmp\tal, ' '\t\t; Is character a space?\n"
  1532. "\t\tjz\tskipws2\t\t; Yes, skip character.\n"
  1533. "\n"
  1534. "\t\tcmp\tal, TAB\t\t; Is character a tab?\n"
  1535. "\t\tjnz\tskipws3\t\t; Yes, skip character.\n"
  1536. "skipws2:\n"
  1537. "\t\tinc\tbx\t\t; Point to next character.\n"
  1538. "\t\tjmp\tSHORT skipws1\t; Continue.\n"
  1539. "skipws3:\n"
  1540. "\t\tmov\tctailaddr, bx\t; Update command tail address.\n"
  1541. "\n"
  1542. "\t\tpop\tbx\n"
  1543. "\t\tpop\tax\n"
  1544. "\n"
  1545. "\t\tret\n"
  1546. "_skipws\t\tENDP\n"
  1547. "\n"
  1548. "; ---------------------------------- ;\n"
  1549. "; Uninstall: Remove TSR from memory. ;\n"
  1550. ";                                    ;\n"
  1551. "; Entry: none                        ;\n"
  1552. ";                                    ;\n"
  1553. "; Exit: does not return              ;\n"
  1554. "; ---------------------------------- ;\n"
  1555. "\n"
  1556. "uninstall\tPROC\tNEAR\n"
  1557. "\t\tmov\tax, 3508h\t; Make sure timer int exists.\n"
  1558. "\t\tint\t21h\n"
  1559. "\n"
  1560. "\t\tmov\tax, es\n"
  1561. "\t\tcmp\tax, psp\n"
  1562. "\t\tjz\tuninstall0\n"
  1563. "\n"
  1564. "\t\tjmp\tNEAR PTR uninstall1\n"
  1565. "uninstall0:\n"
  1566. "\t\tmov\tax, 3509h\t; Make sure key int exists.\n"
  1567. "\t\tint\t21h\n"
  1568. "\n"
  1569. "\t\tmov\tax, es\n"
  1570. "\t\tcmp\tax, psp\n"
  1571. "\t\tjnz\tuninstall1\n"
  1572. "\n"
  1573. "\t\tmov\tax, 3513h\t; Make sure disk int exists.\n"
  1574. "\t\tint\t21h\n"
  1575. "\n"
  1576. "\t\tmov\tax, es\n"
  1577. "\t\tcmp\tax, psp\n"
  1578. "\t\tjnz\tuninstall1\n"
  1579. "\n"
  1580. "\t\tmov\tax, 3528h\t; Make sure idle int exists.\n"
  1581. "\t\tint\t21h\n"
  1582. "\n"
  1583. "\t\tmov\tax, es\n"
  1584. "\t\tcmp\tax, psp\n"
  1585. "\t\tjnz\tuninstall1\n"
  1586. "\n"
  1587. "\t\tmov\tax, 352fh\t; Make sure mux int exists.\n"
  1588. "\t\tint\t21h\n"
  1589. "\n"
  1590. "\t\tmov\tax, es\n"
  1591. "\t\tcmp\tax, psp\n"
  1592. "\t\tjnz\tuninstall1\n"
  1593. "\n"
  1594. "\t\tmov\tax, psp\n"
  1595. "\t\tmov\tes, ax\n"
  1596. "\n"
  1597. "\t\tlds\tdx, es:oldint8h\t; Restore timer int.\n"
  1598. "\t\tmov\tax, 2508h\n"
  1599. "\t\tint\t21h\n"
  1600. "\n"
  1601. "\t\tlds\tdx, es:oldint9h\t; Restore key int.\n"
  1602. "\t\tmov\tax, 2509h\n"
  1603. "\t\tint\t21h\n"
  1604. "\n"
  1605. "\t\tlds\tdx, es:oldint13h ; Restore disk int.\n"
  1606. "\t\tmov\tax, 2513h\n"
  1607. "\t\tint\t21h\n"
  1608. "\n"
  1609. "\t\tlds\tdx, es:oldint28h ; Restore idle int.\n"
  1610. "\t\tmov\tax, 2528h\n"
  1611. "\t\tint\t21h\n"
  1612. "\n"
  1613. "\t\tlds\tdx, es:oldint2fh ; Restore mux int.\n"
  1614. "\t\tmov\tax, 252fh\n"
  1615. "\t\tint\t21h\n"
  1616. "\n"
  1617. "\t\tpush\tcs\n"
  1618. "\t\tpop\tds\n"
  1619. "\n"
  1620. "\t\tmov\tax, psp\t\t; Get resident PSP segment.\n"
  1621. "\t\tmov\tes, ax\n"
  1622. "\n";
  1623.  
  1624. /* --------------------------------------------------------------------- */
  1625.  
  1626. char *listing11 =
  1627.  
  1628. "\t\tcall\t_cleanup\t; Cleanup after setup.\n"
  1629. "\n"
  1630. "\t\tor\tax, ax\t\t; Cleanup successful?\n"
  1631. "\t\tjnz\tuninstall3\t; No, branch.\n"
  1632. "\n";
  1633.  
  1634. /* --------------------------------------------------------------------- */
  1635.  
  1636. char *listing12 =
  1637.  
  1638. "\t\tmov\tah, 49h\t\t; Free memory.\n"
  1639. "\t\tint\t21h\n"
  1640. "\t\tjc\tuninstall3\t; Branch on failure.\n"
  1641. "\n"
  1642. "\t\tlea\tdx, tsr_delmsg\t; Display success message.\n"
  1643. "\t\tmov\tah, 9\n"
  1644. "\t\tint\t21h\n"
  1645. "\n"
  1646. "\t\tmov\tax, 4c00h\t; Exit with OK code.\n"
  1647. "\t\tint\t21h\n"
  1648. "uninstall1:\n"
  1649. "\t\tlea\tdx, tsr_errmsg5\t; Display error message.\n"
  1650. "uninstall2:\n"
  1651. "\t\tmov\tah, 9\n"
  1652. "\t\tint\t21h\n"
  1653. "\n"
  1654. "\t\tmov\tax, 4c01h\t; Exit with error code 1.\n"
  1655. "\t\tint\t21h\n"
  1656. "uninstall3:\n"
  1657. "\t\tlea\tdx, tsr_errmsg8\t; Display severe error message.\n"
  1658. "\t\tjmp\tSHORT uninstall2\n"
  1659. "uninstall\tENDP\n"
  1660. "\n"
  1661. "; ------------------------------------ ;\n"
  1662. "; Unparse: Backup parse pointer by one ;\n"
  1663. ";          character.                  ;\n"
  1664. ";                                      ;\n"
  1665. "; Pointer not backed up if pointing to ;\n"
  1666. "; CR or start of buffer.               ;\n"
  1667. ";                                      ;\n"
  1668. "; Entry: none                          ;\n"
  1669. ";                                      ;\n"
  1670. "; Exit: none                           ;\n"
  1671. ";                                      ;\n"
  1672. "; All other registers preserved.       ;\n"
  1673. "; ------------------------------------ ;\n"
  1674. "\n"
  1675. "_unparse\tPROC\tNEAR\n"
  1676. "\t\tpush\tbx\n"
  1677. "\t\tmov\tbx, ctailaddr\n"
  1678. "\n"
  1679. "\t\tcmp\tbx, 81h\n"
  1680. "\t\tjz\tunparse1\n"
  1681. "\n"
  1682. "\t\tcmp\tBYTE PTR [bx],\tCR\n"
  1683. "\t\tjz\tunparse1\n"
  1684. "\n"
  1685. "\t\tdec\tbx\n"
  1686. "\t\tmov\tctailaddr, bx\n"
  1687. "unparse1:\n"
  1688. "\t\tpop\tbx\n"
  1689. "\n"
  1690. "\t\tret\n"
  1691. "_unparse\tENDP\n"
  1692. "\n"
  1693. "; -------------------------------------- ;\n"
  1694. "; Upper: Convert character to uppercase. ;\n"
  1695. ";                                        ;\n"
  1696. "; Entry: AL - character to convert       ;\n"
  1697. ";                                        ;\n"
  1698. "; Exit: AL - converted character         ;\n"
  1699. ";                                        ;\n"
  1700. "; All other registers preserved.         ;\n"
  1701. "; -------------------------------------- ;\n"
  1702. "\n"
  1703. "upper\t\tPROC\tNEAR\n"
  1704. "\t\tcmp\tal, 'a'\n"
  1705. "\t\tjb\tupper1\n"
  1706. "\n"
  1707. "\t\tcmp\tal, 'z'\n"
  1708. "\t\tja\tupper1\n"
  1709. "\n"
  1710. "\t\tsub\tal, 32\n"
  1711. "upper1:\n"
  1712. "\t\tret\n"
  1713. "upper\t\tENDP\n"
  1714. "\n"
  1715. "_TEXT\t\tENDS\n"
  1716. "\t\tEND\ttsr\n";
  1717.  
  1718. char *banner =
  1719.  
  1720. "╔═══════════════════════════════════════════════════════════╗\n"
  1721. "║ ▒▒▒▒▒  ▒▒▒  ▒▒▒▒▒                                         ║\n"
  1722. "║   ▒   ▒   ▒ ▒   ▒                 TSR v1.5                ║\n"
  1723. "║   ▒   ▒     ▒   ▒                                         ║\n"
  1724. "║   ▒    ▒▒▒  ▒▒▒▒▒ Copyright (C) 1993, Geoff Friesen B.Sc. ║\n"
  1725. "║   ▒       ▒ ▒  ▒            All rights reserved.          ║\n"
  1726. "║   ▒   ▒   ▒ ▒   ▒                                         ║\n"
  1727. "║   ▒    ▒▒▒  ▒   ▒                                         ║\n"
  1728. "╚═══════════════════════════════════════════════════════════╝\n\n";
  1729.  
  1730. int    cbreak        (void);
  1731. void    error        (char *message);
  1732. int    map        (void);
  1733. void    usage        (void);
  1734.  
  1735. void main (int argc, char **argv)
  1736. {
  1737.    FILE *f;
  1738.    int arg;
  1739.    int hotkey = 'T';
  1740.    int include = 0;
  1741.    int scancode = 0x14;
  1742.    int setup_cleanup = 0;
  1743.    int stack = 256;
  1744.    int xparse = 0;
  1745.    char drive [MAXDRIVE];
  1746.    char dir [MAXDIR];
  1747.    char file [MAXFILE];
  1748.    char ext [MAXEXT];
  1749.    char asmspec [MAXPATH];
  1750.    char tsrspec [MAXPATH];
  1751.    char scancodes [] =
  1752.    {
  1753.       30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 50,    /* A-M */
  1754.       49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,    /* N-Z */
  1755.       11,  2,  3,  4,  5,  6,  7,  8,  9, 10, 0            /* 0-9 */
  1756.    };
  1757.  
  1758.    ctrlbrk (cbreak);    /* Install new CTRL-BREAK/CTRL-C handler */
  1759.  
  1760.    fprintf (stderr, banner);
  1761.  
  1762.    if (_osmajor < 3 || _osmajor == 3 && _osminor < 30)
  1763.        error ("DOS 3.30 or higher required");
  1764.  
  1765.    if (argc < 2)
  1766.        usage ();
  1767.  
  1768.    if (argc == 2 &&
  1769.        (!stricmp (argv [1], "/m") || !stricmp (argv [1], "-m")))
  1770.        exit (map ());
  1771.  
  1772.    for (arg = 1; arg < argc; arg++)
  1773.     if (*argv [arg] != '/' && *argv [arg] != '-')
  1774.         break;
  1775.     else
  1776.     if (!strnicmp (argv [arg]+1, "h", 1))
  1777.     {
  1778.         if (!isalnum(argv [arg] [2]))
  1779.         error ("alphanumeric hotkey expected");
  1780.  
  1781.         hotkey = toupper (argv [arg] [2]);
  1782.  
  1783.         scancode = isalpha(hotkey) ? scancodes [hotkey-'A'] :
  1784.                scancodes [hotkey-'0'+26];
  1785.     }
  1786.     else
  1787.     if (!stricmp (argv [arg]+1, "i"))
  1788.         include = 1;
  1789.     else
  1790.     if (!strnicmp (argv [arg]+1, "sc", 2))
  1791.         setup_cleanup = 1;
  1792.     else
  1793.     if (!strnicmp (argv [arg]+1, "s", 1))
  1794.     {
  1795.         stack = atoi (argv [arg]+2);
  1796.  
  1797.         if (stack < 256 || stack > 8192)
  1798.         error ("stack size out of range");
  1799.     }
  1800.     else
  1801.     if (!stricmp (argv [arg]+1, "x"))
  1802.         xparse = 1;
  1803.     else
  1804.         usage ();
  1805.  
  1806.    if (arg == argc)
  1807.        error ("tsrspec is missing");
  1808.  
  1809.    strcpy (tsrspec, argv [argc-1]);
  1810.  
  1811.    if (!(fnsplit (tsrspec, drive, dir, file, ext) & EXTENSION))
  1812.    {
  1813.        strcpy (ext, ".TSR");
  1814.        fnmerge (tsrspec, drive, dir, file, ext);
  1815.    }
  1816.    else
  1817.        if (stricmp (ext, ".TSR"))
  1818.        error ("invalid extension (.TSR expected)");
  1819.  
  1820.    strcpy (ext, ".ASM");
  1821.    fnmerge (asmspec, drive, dir, file, ext);
  1822.  
  1823.    if ((f = fopen (asmspec, "wt")) == NULL)
  1824.        error ("unable to create .ASM file");
  1825.  
  1826.    if (fprintf (f, "; %s%s", asmspec, listing1) == EOF ||
  1827.        fprintf (f, "%c%s", hotkey, listing2) == EOF ||
  1828.        fprintf (f, "%02xh%s", scancode, listing3) == EOF ||
  1829.        fprintf (f, "\"TSR:%s\"%s", file, listing4) == EOF ||
  1830.        fprintf (f, "\t\tDB\t%d DUP (?)\n"
  1831.            "stack_\t\tLABEL\tBYTE\n"
  1832.            "\n"
  1833.            "\t\tINCLUDE %s\n", stack, tsrspec) == EOF ||
  1834.        include && fprintf (f, "\t\tINCLUDE EXTRA.ASM\n") == EOF ||
  1835.        fprintf (f, "%s", listing5) == EOF ||
  1836.        setup_cleanup && fprintf (f, "%s", listing6) == EOF ||
  1837.        fprintf (f, "%s", listing7) == EOF ||
  1838.        xparse && fprintf (f, "%s", listing8_1) == EOF ||
  1839.        fprintf (f, "%s", listing8_2) == EOF ||
  1840.        setup_cleanup && fprintf (f, "%s", listing9) == EOF ||
  1841.        fprintf (f, "%s", listing10) == EOF ||
  1842.        setup_cleanup && fprintf (f, "%s", listing11) == EOF ||
  1843.        fprintf (f, "%s", listing12) == EOF)
  1844.        error ("unable to write to .ASM file");
  1845.  
  1846.    (void) fcloseall ();
  1847.    fprintf (stderr, "tsr: %s successfully generated\n", asmspec);
  1848.    exit (OK);
  1849. }
  1850.  
  1851. /* -------------------- */
  1852. /* int cbreak (void);   */
  1853. /*                      */
  1854. /* Disable CTRL-BREAKs. */
  1855. /* -------------------- */
  1856.  
  1857. int cbreak (void)
  1858. {
  1859.    return IGNORE;
  1860. }
  1861.  
  1862. /* --------------------------------------------- */
  1863. /* void error (char *message);                   */
  1864. /*                                               */
  1865. /* Display the specified error message and exit. */
  1866. /* --------------------------------------------- */
  1867.  
  1868. void error (char *message)
  1869. {
  1870.    (void) fcloseall ();
  1871.    fprintf (stderr, "tsr: %s\n", message);
  1872.    exit (ERROR);
  1873. }
  1874.  
  1875. /* ------------------------------- */
  1876. /* int map (void);                 */
  1877. /*                                 */
  1878. /* Display a map of resident TSRs. */
  1879. /* Return OK or ERROR.             */
  1880. /* ------------------------------- */
  1881.  
  1882. int map (void)
  1883. {
  1884.    char typemcb;
  1885.    unsigned i, ntsrs = 0, segment = 0x40;
  1886.  
  1887.    do
  1888.    {
  1889.        if (peekb(segment, 0) == BLOCMCB)    /* Found first MCB?      */
  1890.        if (peek(segment, 1) == segment+1)    /* First MCB owns ...    */
  1891.            break;                /* ... following segment */
  1892.  
  1893.        if (++segment == 0xa000)            /* Goto 640K segment ... */
  1894.        {                    /* ... even if less mem  */
  1895.        fprintf (stderr, "tsr: bad MCB chain\n");
  1896.        return ERROR;
  1897.        }
  1898.    }
  1899.    while (1);
  1900.  
  1901.    puts ("---   ------   ---");
  1902.    puts ("PSP   HOTKEY   TSR");
  1903.    puts ("---   ------   ---\n");
  1904.  
  1905.    do
  1906.    {
  1907.       if ((~peekb(segment+1, SIGOFS) == 'T') &&
  1908.       (peekb(segment+1, SIGOFS+1) == 'S') &&
  1909.       (peekb(segment+1, SIGOFS+2) == 'R'))
  1910.       {
  1911.       printf ("%04X  ", ++segment);        /* Point to PSP          */
  1912.  
  1913.       printf ("ALT-%c    ", peekb(segment, KEYOFS));
  1914.  
  1915.       putchar('T');
  1916.       for (i = SIGOFS+1; putchar(peekb(segment, i++));)
  1917.            ;
  1918.       puts ("");
  1919.  
  1920.       ntsrs++;
  1921.       segment--;                /* Point to MCB          */
  1922.        }
  1923.  
  1924.       if (peekb(segment, 0) == LASTMCB)
  1925.       break;
  1926.  
  1927.       segment += (peek(segment, 3)+1);        /* Point to next MCB     */
  1928.       typemcb = peekb(segment, 0);              /* Obtain MCB type       */
  1929.  
  1930.       if (typemcb != BLOCMCB && typemcb != LASTMCB)
  1931.       {
  1932.       fprintf (stderr, "tsr: bad MCB chain\n");
  1933.       return ERROR;
  1934.       }
  1935.    }
  1936.    while (1);
  1937.  
  1938.    if (ntsrs)
  1939.        puts ("");
  1940.  
  1941.    printf ("tsr: found %d tsr%s", ntsrs, (ntsrs != 1) ? "s.\n" : ".\n");
  1942.    return OK;
  1943. }
  1944.  
  1945. /* --------------------------------------------- */
  1946. /* void usage (void);                            */
  1947. /*                                               */
  1948. /* Display usage information when user enters an */
  1949. /* invalid command-line.  Exit program.          */
  1950. /* --------------------------------------------- */
  1951.  
  1952. void usage (void)
  1953. {
  1954.    char *_usage =
  1955.  
  1956.    "bad command line\n\n"
  1957.    "Command-line format:\n"
  1958.    "\n"
  1959.    "tsr options tsrspec\n"
  1960.    "\n"
  1961.    "options = map | [hotkey] [include] [setup_cleanup] [stack] [xparse]\n"
  1962.    "\n"
  1963.    "map = (\"/\"|\"-\") \"m\"\n"
  1964.    "hotkey = (\"/\"|\"-\") \"h\" x\n"
  1965.    "include = (\"/\"|\"-\") \"i\"\n"
  1966.    "setup_cleanup = (\"/\"|\"-\") \"sc\"\n"
  1967.    "stack = (\"/\"|\"-\") \"s\" y\n"
  1968.    "xparse = (\"/\"|\"-\") \"x\"\n"
  1969.    "\n"
  1970.    "x is either \"A\"-\"Z\" or \"0\"-\"9\" (default is T)\n"
  1971.    "y is a byte value from 256 to 8192 (default is 256)\n"
  1972.    "tsrspec defines the .TSR file to be TSRed\n";
  1973.  
  1974.    error (_usage);
  1975. }